package com.dianwoba.core.solr.where;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import com.dianwoba.core.solr.SolrConditionType;

/**
 * WHERE抽象实现
 * @author 堵成杰
 * @since 2.0
 * 
 */
public abstract class AbstractSolrWhere<T extends AbstractSolrWhere<T>> implements SolrWhere{

	/**
	 * 查询条件字符串列表
	 */
	protected List<String> criteriaList = new ArrayList<String>();

	/**
	 * 总查询条件字符串
	 */
	protected String criteria;

	/**
	 * 比较类型查询条件字符串列表
	 */
	protected Map<String,Condition> mergeCandidateConditions = new LinkedHashMap<String, Condition>();

	/**
	 * 是否包含否定
	 */
	protected boolean containsNot = false;

	@SuppressWarnings("unchecked")
	public T eq(String propertyName, Object value){
		this.addCondition(SolrConditionType.EQ, propertyName, value);
		return (T)this;
	}
	
	@SuppressWarnings("unchecked")
	public T ne(String propertyName, Object value){
		this.addCondition(SolrConditionType.NE, propertyName, value);
		return (T)this;
	}
	
	@SuppressWarnings("unchecked")
	public T lt(String propertyName, Object value){
		this.addCondition(SolrConditionType.LT, propertyName, value);
		return (T)this;
	}
	
	@SuppressWarnings("unchecked")
	public T le(String propertyName, Object value){
		this.addCondition(SolrConditionType.LE, propertyName, value);
		return (T)this;
	}
	
	@SuppressWarnings("unchecked")
	public T gt(String propertyName, Object value){
		this.addCondition(SolrConditionType.GT, propertyName, value);
		return (T)this;
	}
	
	@SuppressWarnings("unchecked")
	public T ge(String propertyName, Object value){
		this.addCondition(SolrConditionType.GE, propertyName, value);
		return (T)this;
	}
	
	@SuppressWarnings("unchecked")
	public T in(String propertyName, Object value){
		this.addCondition(SolrConditionType.IN, propertyName, value);
		return (T)this;
	}
	
	@SuppressWarnings("unchecked")
	public T not_in(String propertyName, Object value){
		this.addCondition(SolrConditionType.NOT_IN, propertyName, value);
		return (T)this;
	}
	
	@SuppressWarnings("unchecked")
	public T like(String propertyName, Object value){
		this.addCondition(SolrConditionType.LIKE, propertyName, value);
		return (T)this;
	}
	
	public boolean containsNot(){
		return containsNot;
	}
	
	/**
	 * 设定查询条件
	 * @param solrConditionType	查询条件类型
	 * @param propertyName		属性名称
	 * @param value				属性值
	 */
	protected void addCondition(SolrConditionType solrConditionType,
			String propertyName, Object value) {
		if (value == null){
			return;
		}
		if(value instanceof String && StringUtils.isEmpty(((String)value).trim())){
			return;
		}

		if(!containsNot){
			containsNot = solrConditionType.isNotCondition();
		}

		//当查询条件为非比较类型的时候
		if(!solrConditionType.isCompare() || List.class.isAssignableFrom(value.getClass())){
			
			//将序列化以后的查询条件放入查询条件字符串列表中
			criteriaList.add(solrConditionType.getCondition(propertyName, value));
			
		//当查询条件为比较类型的时候
		}else{

			//取出比较的前提条件
			Condition beforeInputtedCondition = null;
			switch (solrConditionType) {
			case GE:
				beforeInputtedCondition = mergeCandidateConditions.
											get(getKey(propertyName, SolrConditionType.LE));
				break;
			case GT:
				beforeInputtedCondition = mergeCandidateConditions.
											get(getKey(propertyName, SolrConditionType.LT));
				break;
			case LE:
				beforeInputtedCondition = mergeCandidateConditions.
											get(getKey(propertyName, SolrConditionType.GE));
				break;
			case LT:
				beforeInputtedCondition = mergeCandidateConditions.
											get(getKey(propertyName, SolrConditionType.GT));
				break;
			default:
				break;
			}

			//当该比较条件包含前提条件时
			if(beforeInputtedCondition != null){
				String criteria = beforeInputtedCondition.conditionType
					.getCondition(propertyName, beforeInputtedCondition.value,value);
				criteriaList.add(criteria);
				mergeCandidateConditions.remove(getKey(propertyName, 
														beforeInputtedCondition.conditionType));
			}else{
				mergeCandidateConditions.put(getKey(propertyName, solrConditionType), 
												new Condition(solrConditionType,propertyName,value));
			}
		}
	}
	
	/**
	 * 取得总查询条件字符串
	 */
	public String getCriteria() {

		if(criteria != null){
			return criteria;
		}

		criteria = getCriteriaCore();

		return criteria;

	}

	/**
	 * 拼装总查询条件字符串
	 */
	protected String getCriteriaCore(){
		for (String property : mergeCandidateConditions.keySet()) {
			Condition condition = mergeCandidateConditions.get(property);
			criteriaList.add(condition.conditionType.
										getCondition(condition.propertyName, condition.value));
		}

		return StringUtils.join(criteriaList.toArray(), getConnector());
	}

	public String getConnector(){
		return " AND ";
	}

	class Condition{
		public SolrConditionType conditionType;
		public String propertyName;
		public Object value;

		public Condition(SolrConditionType conditionType,String propertyName,Object value){
			this.conditionType = conditionType;
			this.propertyName = propertyName;
			this.value = value;
		}
	}
	/**
	 * 获取比较条件存放KEY
	 * @param propertyName
	 * @param solrConditionType
	 * @return
	 */
	protected String getKey(String propertyName,SolrConditionType solrConditionType){
		return propertyName + "__" + solrConditionType.name();
	}
}
